/**********************************************************************************
// DemoInput
// 
// Creation:	12 Oct 2007
// Updated:		27 May 2011
// Compiler:	Visual Studio 2010
//
// Notes:		Test the direct input functions
//				Use Direct Input for keyboard state
//
**********************************************************************************/

#define WIN32_LEAN_AND_MEAN  // just say no to MFC

#include "Resources.h"
#include "Anabele.h"	

/**********************************************************************************/
/*                          InputDemo Class                                       */
/**********************************************************************************/

class InputDemo: public D3DGame
{
private:
	Sprite * demobox;
	Sprite * demobar;

	SceneManager scene;
	Input input;

	bool keyboardOn;
	bool mouseOn;
	bool joystickOn;

	Circle circ;
	Poly   plane;

	char text[256];
	bool viewBR;

public:
	InputDemo();
	void InitObjects();

	void GameInit();
	void GameLogic();
	void GameDraw();
	void GameShutDown();
	void UnloadResources();
	void LoadResources();
};

/**********************************************************************************/

InputDemo::InputDemo()
{
	viewBR     = false;
	keyboardOn = false;
	mouseOn    = false;
	joystickOn = false;
}

/**********************************************************************************/
void InputDemo::InitObjects()
{
	Point vlist[24] = {Point(1,11),
                          Point(2,8),
						  Point(1,7),
						  Point(1,-1),
						  Point(3,-1),
						  Point(3,-2),
						  Point(11,-3),
						  Point(11,-6),
						  Point(3,-7),
						  Point(2,-8),
						  Point(1,-8),
						  Point(1,-7),
						  Point(-1,-7),
						  Point(-1,-8),
						  Point(-2,-8),
						  Point(-3,-7),
						  Point(-11,-6),
						  Point(-11,-3),
						  Point(-3,-2),
						  Point(-3,-1),
						  Point(-1,-1),
						  Point(-1,7),
						  Point(-2,8),
						  Point(-1, 11)};

	circ = Circle(200.0f);
	plane = Poly(vlist, 24);
	plane.Scale(8.0f, 8.0f);
	
	circ.MoveTo(GetWindowWidth()/2.0f, GetWindowHeight()/2.0f);
	plane.MoveTo(GetWindowWidth()/2.0f, GetWindowHeight()/2.0f);
}

/**********************************************************************************/

void InputDemo::GameInit()
{
	Point p1 = Point(1,1);
	Point p2 = Point(2,2);
	p2=p1;

	srand(GetTickCount());

	InitObjects();

	input.Initialize();

	keyboardOn = input.InitializeKeyboard();
	mouseOn    = input.InitializeMouse();
	joystickOn = input.InitializeJoystick();

	scene.RegisterStatic(circ);
	scene.RegisterMoving (plane);

	LoadResources();
}

/**********************************************************************************/

void InputDemo::LoadResources()
{
	demobox = new Sprite("Resources/demoBox.png");
	demobox->MoveTo(155, 100);
	
	demobar = new Sprite("Resources/demoBigBar.png");
	demobar->MoveTo(GetWindowWidth()/2.0f, GetWindowHeight()-30.0f);
}

/**********************************************************************************/

void InputDemo::UnloadResources()
{
	if (demobar) delete demobar;
	if (demobox) delete demobox;
}

/**********************************************************************************/

void InputDemo::GameShutDown()
{
	UnloadResources();
}

/**********************************************************************************/

void InputDemo::GameLogic()
{
	
	circ.color = Color(255,255,255);
	plane.color = Color(255,255,255);

	// Quits by pressing ESC
	EndsOnEscape();

	// ==== Keyboard input ====
	if (keyboardOn)
	{
		// Update keyboard state
		input.GetKeyboardState();

		// Restart Game (R)
		if (input.KeyPressed(DIK_R))
			InitObjects();

		if (joystickOn)
		{
			// Select Next Joystick (Page Down)
			if (input.KeyPressRelease(DIK_PGDN))
				input.JoystickSelectNext();

			// Select Previous Joystick (Page Up)
			if (input.KeyPressRelease(DIK_PGUP))
				input.JoystickSelectPrev();
		}

		// Enable Bounding Box (E)
		if (input.KeyPressRelease(DIK_E))
			viewBR = true;

		// Disable Bounding Box (D)
		if (input.KeyPressRelease(DIK_D))
			viewBR = false;

		// Scale (A and S)
		if (input.KeyPressed(DIK_A)) // scale up
			plane.Scale(1.1f, 1.1f);
		if (input.KeyPressed(DIK_S)) // scale down
			plane.Scale(0.9f, 0.9f);

		// Rotate (Z and X)
		if (input.KeyPressed(DIK_Z)) // rotate left
			plane.Rotate(-5);
		if (input.KeyPressed(DIK_X)) // rotate right
			plane.Rotate(5);

		// Translate 
		// (Right, Left, Up and Down)
		if (input.KeyPressed(DIK_RIGHT)) // translate right
			plane.Translate(10,0);
		if (input.KeyPressed(DIK_LEFT))  // translate left
			plane.Translate(-10,0);    
		if (input.KeyPressed(DIK_UP))    // translate up
			plane.Translate(0,-10); 
		if (input.KeyPressed(DIK_DOWN))  // translate down
			plane.Translate(0,10);
	}


	// ==== Mouse input ====
	if (mouseOn)
	{
		// Update mouse state
		input.GetMouseState();

		// Translate (mouse movement)
		plane.Translate(input.MouseAxis(MouseAxisX)*2.0f, input.MouseAxis(MouseAxisY)*2.0f);

		// Scale (mouse wheel)
		if (input.MouseAxis(MouseWheel)>0)
			plane.Scale(1.1f,1.1f);
		if (input.MouseAxis(MouseWheel)<0)
			plane.Scale(0.9f,0.9f);

		// Rotate (mouse buttons)
		if (input.MouseButton(MouseLeftButton))
			plane.Rotate(-10.0f);
		if (input.MouseButton(MouseRightButton))
			plane.Rotate(10.0f);

		// Fire (mouse middle button)
		if (input.MouseButton(MouseMiddleButton))
			InitObjects();
	}

	// ==== Joystick input ====
	if (joystickOn)
	{
		// Update joystick state
		input.GetJoystickState();
	
		// Restart Game
		if (input.JoystickButton(7))
			InitObjects();

		// Translate (left analog stick)
		plane.Translate(input.JoystickAxis(JoyAxisX)/50.0f, input.JoystickAxis(JoyAxisY)/50.0f);
		
		switch(input.JoystickPov(0))
		{
		case 0:
			plane.Translate(0.0f, -10.0f); // go up
			break;
		case 4500:
			plane.Translate(10.0f, -10.0f); // go up and right
			break;
		case 9000:
			plane.Translate(10.0f, 0.0f); // go right
			break;
		case 13500:
			plane.Translate(10.0f, 10.0f); // go down and right
			break;
		case 18000:
			plane.Translate(0.0f, 10.0f); // go down
			break;
		case 22500:
			plane.Translate(-10.0f, 10.0f); // go down and left
			break;
		case 27000:
			plane.Translate(-10.0f, 0.0f); // go left
			break;
		case 31500:
			plane.Translate(-10.0f, -10.0f); // go left and up
			break;
		}

		// Scale (Buttons 5 and 6)
		if (input.JoystickButton(4))
			plane.Scale(1.1f,1.1f);
		if (input.JoystickButton(5))
			plane.Scale(0.9f,0.9f);
	
		// Rotate (right analog stick)
		if (input.JoystickAxis(JoyAxisRX)<0)
			plane.Rotate(float(input.JoystickAxis(JoyAxisRX)/100));
		if (input.JoystickAxis(JoyAxisRX)>0)
			plane.Rotate(float(input.JoystickAxis(JoyAxisRX)/100));

		// Rotate (AxisZ)
		if (input.JoystickAxis(JoyAxisZ)<0)
			plane.Rotate(float(input.JoystickAxis(JoyAxisZ)/100));
		if (input.JoystickAxis(JoyAxisZ)>0)
			plane.Rotate(float(input.JoystickAxis(JoyAxisZ)/100));

		// Enable Bounding Box (Button 1)
		if (input.JoystickButton(0))
			viewBR = true;

		// Disable Bounding Box (Button 2)
		if (input.JoystickButton(1))
			viewBR = false;
	}

	
	// test for collision
	if (scene.CollisionDetection())
	{
		pair<GameObject*,GameObject*> pairObjs;

		while ((pairObjs = scene.OnCollisionObjects()) != pair<GameObject*,GameObject*>(nullptr,nullptr))
		{
			((Geometry*) pairObjs.first)->color = Color(65,250,0);
			((Geometry*) pairObjs.second)->color = Color(65,250,0);
		}
	}
} 

/**********************************************************************************/

void InputDemo::GameDraw()
{
	// Lock Screen for pixel plotting functions
	LockScreen();

	// Draw polygons
	circ.Draw();
	plane.Draw();
				
	// Draw the bounding boxes
	if (viewBR)
	{
		plane.GetBBox().color = Color(255,40,70);
		plane.GetBBox().Draw();
	}

	UnLockScreen();


	demobox->Draw();
	demobar->Draw();

	sprintf_s(text, "Input Demo");
	sysFont->Draw(55, 40, text);

	sprintf_s(text, "Keyboard / Mouse / Joystick Input");
	sysFont->Draw(55, 80, text);

	sprintf_s(text, "<E> - Enable the bounding box");
	sysFont->Draw(55, 100, text);

	sprintf_s(text, "<D> - Disable the bounding box");
	sysFont->Draw(55, 120, text);
	
	sprintf_s(text, "<R> - Restart");
	sysFont->Draw(55, 140, text);


	if (joystickOn)
	{
		sprintf_s(text, "<A> and <S> Scale   <Z> and <X> Rotate   <Arrows> Translate  <PgUp> Prev Joy   <PgDown> Next Joy");
		sysFont->Draw(0, GetWindowHeight()-37, text, Color(255,255,255), GetWindowWidth(), 30, DT_CENTER);
	}
	else
	{
		sprintf_s(text, "<A> and <S> Scale   <Z> and <X> Rotate   <Arrows> Translate");
		sysFont->Draw(0, GetWindowHeight()-37, text, Color(255,255,255), GetWindowWidth(), 30, DT_CENTER);
	}

	if (joystickOn)
	{
		sprintf_s(text, "Selected Joystick: %s", input.JoystickName());
		sysFont->Draw(40, 200, text);		

		list<JoyObjs> joyObjList = input.JoystickObjects();
		list<JoyObjs>::const_iterator pos;
		int i = 230;

		int bt = 0;
		int pov = 0;

		for (pos = joyObjList.begin(); pos != joyObjList.end(); ++pos)
		{
			if (pos->guid == GUID_XAxis)
				sprintf_s(text, "Joystick %s: %ld", pos->name.c_str(), input.JoystickAxis(JoyAxisX));
			if (pos->guid == GUID_YAxis)
				sprintf_s(text, "Joystick %s: %ld", pos->name.c_str(), input.JoystickAxis(JoyAxisY));
			if (pos->guid == GUID_ZAxis)
				sprintf_s(text, "Joystick %s: %ld", pos->name.c_str(), input.JoystickAxis(JoyAxisZ));
			if (pos->guid == GUID_RxAxis)
				sprintf_s(text, "Joystick %s: %ld", pos->name.c_str(), input.JoystickAxis(JoyAxisRX));
			if (pos->guid == GUID_RyAxis)
				sprintf_s(text, "Joystick %s: %ld", pos->name.c_str(), input.JoystickAxis(JoyAxisRY));
			if (pos->guid == GUID_RzAxis)
				sprintf_s(text, "Joystick %s: %ld", pos->name.c_str(), input.JoystickAxis(JoyAxisRZ));
			if (pos->guid == GUID_Button)
				sprintf_s(text, "Joystick %s: %ld", pos->name.c_str(), input.JoystickButton(bt++));
			if (pos->guid == GUID_POV)
				sprintf_s(text, "Joystick %s: %ld", pos->name.c_str(), input.JoystickPov(pov++));
			if (pos->guid == GUID_Slider)
				sprintf_s(text, "Joystick Slider");
			if (pos->guid == GUID_Unknown)
				sprintf_s(text, "Joystick Unknown");
			if (pos->guid == GUID_Key)
				sprintf_s(text, "Joystick Key");
			
			sysFont->Draw(40, i, text);
			i = i + 20;	
		}
	}	
} 


/**********************************************************************************/
/*                                  WinMain                                       */
/**********************************************************************************/

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	InputDemo inputdemo;

	//inputdemo.SetWindowMode(WINDOWED);
	//inputdemo.SetWindowSize(1024,768);
	inputdemo.SetWindowBgColor(10,25,55);
	inputdemo.SetWindowTitle(string("Direct Input Demo"));
	inputdemo.SetWindowIcon(LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)));
	inputdemo.ShowWindowCursor(false);
	inputdemo.Initialize(hInstance);
	inputdemo.Start();
	
	return 0;

}

/**********************************************************************************/